home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / main.c < prev    next >
C/C++ Source or Header  |  2001-06-30  |  17KB  |  644 lines

  1. /*
  2.  * Modifications Copyright 1993, 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
  3.  * Original X11 Port Copyright 1990 by Jeff Sparkes.
  4.  *  Permission to use, copy, modify, and distribute this software and its
  5.  *  documentation for any purpose and without fee is hereby granted,
  6.  *  provided that the above copyright notice appear in all copies and that
  7.  *  both that copyright notice and this permission notice appear in
  8.  *  supporting documentation.
  9.  *
  10.  * Copyright 1989 by Georgia Tech Research Corporation, Atlanta, GA 30332.
  11.  *  All Rights Reserved.  GTRC hereby grants public use of this software.
  12.  *  Derivative works based on this software must incorporate this copyright
  13.  *  notice.
  14.  */
  15.  
  16. /*
  17.  *    main.c
  18.  *        A 3270 Terminal Emulator for X11
  19.  *        Main proceudre.
  20.  */
  21.  
  22. #include "globals.h"
  23. #ifndef AMIGA
  24. #include <sys/wait.h>
  25. #endif
  26. #include <X11/StringDefs.h>
  27. #include <X11/Core.h>
  28. #include <X11/Shell.h>
  29. #include <X11/Xatom.h>
  30. #include <signal.h>
  31. #include "appres.h"
  32. #include "3270ds.h"
  33. #include "resources.h"
  34.  
  35. #include "actionsc.h"
  36. #include "ansic.h"
  37. #include "charsetc.h"
  38. #include "ctlrc.h"
  39. #include "ftc.h"
  40. #include "hostc.h"
  41. #include "keymapc.h"
  42. #include "kybdc.h"
  43. #include "macrosc.h"
  44. #include "menubarc.h"
  45. #include "popupsc.h"
  46. #include "resourcesc.h"
  47. #include "savec.h"
  48. #include "screenc.h"
  49. #include "selectc.h"
  50. #include "statusc.h"
  51. #include "telnetc.h"
  52. #include "togglesc.h"
  53. #include "trace_dsc.h"
  54. #include "utilc.h"
  55.  
  56. /* Externals */
  57. #if defined(USE_APP_DEFAULTS) /*[*/
  58. extern const char *app_defaults_version;
  59. #ifdef AMIGA
  60. const char *app_defaults_version="3.2.14";
  61. #endif
  62. #else /*][*/
  63. extern String    color_fallbacks[];
  64. extern String    mono_fallbacks[];
  65. #endif /*]*/
  66.  
  67. /* Globals */
  68. char           *programname;
  69. Display        *display;
  70. int             default_screen;
  71. Window          root_window;
  72. int             screen_depth;
  73. Widget          toplevel;
  74. XtAppContext    appcontext;
  75. Atom            a_delete_me, a_save_yourself, a_3270, a_registry, a_iso8859,
  76.         a_ISO8859, a_encoding, a_1, a_state;
  77. char        full_model_name[13] = "IBM-";
  78. char           *model_name = &full_model_name[4];
  79. Pixmap          gray;
  80. XrmDatabase     rdb;
  81. AppRes          appres;
  82. int        children = 0;
  83. Boolean        exiting = False;
  84.  
  85. /* Statics */
  86. static void    peek_at_xevent(XEvent *);
  87. static XtErrorMsgHandler old_emh;
  88. static void    trap_colormaps(String, String, String, String, String *,
  89.             Cardinal *);
  90. static Boolean  colormap_failure = False;
  91. #if defined(LOCAL_PROCESS) /*[*/
  92. static void    parse_local_process(int *argcp, char **argv, char **cmds);
  93. #endif /*]*/
  94. static void    parse_set_clear(int *, char **);
  95. static void    label_init(void);
  96. static char    *user_title = CN;
  97. static char    *user_icon_name = CN;
  98.  
  99. XrmOptionDescRec options[]= {
  100.     { OptActiveIcon,DotActiveIcon,    XrmoptionNoArg,        ResTrue },
  101.     { OptAplMode,    DotAplMode,    XrmoptionNoArg,        ResTrue },
  102.     { OptCharClass,    DotCharClass,    XrmoptionSepArg,    NULL },
  103.     { OptCharset,    DotCharset,    XrmoptionSepArg,    NULL },
  104.     { OptClear,    ".xxx",        XrmoptionSkipArg,    NULL },
  105.     { OptColorScheme,DotColorScheme,XrmoptionSepArg,    NULL },
  106.     { OptDsTrace,    DotDsTrace,    XrmoptionNoArg,        ResTrue },
  107.     { OptEmulatorFont,DotEmulatorFont,XrmoptionSepArg,    NULL },
  108.     { OptExtended,    DotExtended,    XrmoptionNoArg,        ResTrue },
  109.     { OptIconName,    ".iconName",    XrmoptionSepArg,    NULL },
  110.     { OptIconX,    ".iconX",    XrmoptionSepArg,    NULL },
  111.     { OptIconY,    ".iconY",    XrmoptionSepArg,    NULL },
  112.     { OptKeymap,    DotKeymap,    XrmoptionSepArg,    NULL },
  113.     { OptKeypadOn,    DotKeypadOn,    XrmoptionNoArg,        ResTrue },
  114.     { OptM3279,    DotM3279,    XrmoptionNoArg,        ResTrue },
  115.     { OptModel,    DotModel,    XrmoptionSepArg,    NULL },
  116.     { OptMono,    DotMono,    XrmoptionNoArg,        ResTrue },
  117.     { OptNoScrollBar,DotScrollBar,    XrmoptionNoArg,        ResFalse },
  118.     { OptOnce,    DotOnce,    XrmoptionNoArg,        ResTrue },
  119.     { OptOversize,    DotOversize,    XrmoptionSepArg,    NULL },
  120.     { OptPort,    DotPort,    XrmoptionSepArg,    NULL },
  121.     { OptReconnect,    DotReconnect,    XrmoptionNoArg,        ResTrue },
  122.     { OptSaveLines,    DotSaveLines,    XrmoptionSepArg,    NULL },
  123.     { OptScripted,    DotScripted,    XrmoptionNoArg,        ResTrue },
  124.     { OptScrollBar,    DotScrollBar,    XrmoptionNoArg,        ResTrue },
  125.     { OptSet,    ".xxx",        XrmoptionSkipArg,    NULL },
  126.     { OptTermName,    DotTermName,    XrmoptionSepArg,    NULL },
  127.     { OptTraceFile,    DotTraceFile,    XrmoptionSepArg,    NULL }
  128. };
  129. int num_options = XtNumber(options);
  130.  
  131. /* Fallback resources. */
  132. #if defined(USE_APP_DEFAULTS) /*[*/
  133. static String fallbacks[] = {
  134.     "*adVersion:    fallback",
  135.     NULL
  136. };
  137. #else /*][*/
  138. static String *fallbacks = color_fallbacks;
  139. #endif /*]*/
  140.  
  141. struct toggle_name toggle_names[N_TOGGLES] = {
  142.     { ResMonoCase,        MONOCASE },
  143.     { ResAltCursor,       ALT_CURSOR },
  144.     { ResCursorBlink,     CURSOR_BLINK },
  145.     { ResShowTiming,      SHOW_TIMING },
  146.     { ResCursorPos,       CURSOR_POS },
  147. #if defined(X3270_TRACE) /*[*/
  148.     { ResDsTrace,         DS_TRACE },
  149. #endif /*]*/
  150.     { ResScrollBar,       SCROLL_BAR },
  151. #if defined(X3270_ANSI) /*[*/
  152.     { ResLineWrap,        LINE_WRAP },
  153. #endif /*]*/
  154.     { ResBlankFill,       BLANK_FILL },
  155. #if defined(X3270_TRACE) /*[*/
  156.     { ResScreenTrace,     SCREEN_TRACE },
  157.     { ResEventTrace,      EVENT_TRACE },
  158. #endif /*]*/
  159.     { ResMarginedPaste,   MARGINED_PASTE },
  160.     { ResRectangleSelect, RECTANGLE_SELECT }
  161. };
  162.  
  163.  
  164. static void
  165. usage(const char *msg)
  166. {
  167.     if (msg != CN)
  168.         XtWarning(msg);
  169. #if defined(X3270_MENUS) /*[*/
  170.     xs_error("Usage: %s [options] [[ps:][LUname@]hostname[:port]]", programname);
  171. #else /*][*/
  172.     xs_error("Usage: %s [options] [ps:][LUname@]hostname[:port]", programname);
  173. #endif /*]*/
  174. }
  175.  
  176. static void
  177. no_minus(char *arg)
  178. {
  179.     if (arg[0] == '-')
  180.         usage(xs_buffer("Unknown or incomplete option: %s", arg));
  181. }
  182.  
  183. int
  184. main(int argc, char *argv[])
  185. {
  186. #if !defined(USE_APP_DEFAULTS) /*[*/
  187.     char    *dname;
  188.     int    i;
  189. #endif /*]*/
  190.     Atom    protocols[2];
  191.     char    *cl_hostname = CN;
  192.     int    ovc, ovr;
  193.     char    junk;
  194.     int    sl;
  195.  
  196.     /* Figure out who we are */
  197.     programname = strrchr(argv[0], '/');
  198.     if (programname)
  199.         ++programname;
  200.     else
  201.         programname = argv[0];
  202.  
  203. #ifdef AMIGA
  204. if (99000>stacksize())
  205.    {
  206.    printf("This application requires at least 100000 bytes of stack!\n");
  207.    exit(1);
  208.    }
  209.  
  210. AMIGA_INIT_CME();
  211. AMIGA_INIT_CMEBSB();
  212. AMIGA_INIT_CMELINE();
  213. AMIGA_INIT_CMPLXMENU();
  214. AMIGA_INIT_HUSK();
  215. #endif
  216.  
  217.     /* Save a copy of the command-line args for merging later. */
  218.     save_args(argc, argv);
  219.  
  220. #if !defined(USE_APP_DEFAULTS) /*[*/
  221.     /*
  222.      * Figure out which fallbacks to use, based on the "-mono"
  223.      * switch on the command line, and the depth of the display.
  224.      */
  225.     dname = CN;
  226.     for (i = 1; i < argc; i++) {
  227.         if (!strcmp(argv[i], "-mono"))
  228.             fallbacks = mono_fallbacks;
  229.         else if (!strcmp(argv[i], "-display") && argc > i)
  230.             dname = argv[i+1];
  231.     }
  232.     display = XOpenDisplay(dname);
  233.     if (display == (Display *)NULL)
  234.         XtError("Can't open display");
  235.     if (DefaultDepthOfScreen(XDefaultScreenOfDisplay(display)) == 1)
  236.         fallbacks = mono_fallbacks;
  237.     XCloseDisplay(display);
  238. #endif /*]*/
  239.  
  240.     /* Initialize. */
  241.     toplevel = XtVaAppInitialize(
  242.         &appcontext,
  243. #if defined(USE_APP_DEFAULTS) /*[*/
  244.         "X3270",
  245. #else /*][*/
  246.         "X3270xad",    /* explicitly _not_ X3270 */
  247. #endif /*]*/
  248.         options, num_options,
  249.         &argc, argv,
  250.         fallbacks,
  251.         XtNinput, True,
  252.         XtNallowShellResize, False,
  253.         NULL);
  254.     display = XtDisplay(toplevel);
  255.     rdb = XtDatabase(display);
  256.  
  257.     /* Merge in the profile. */
  258.     merge_profile(&rdb);
  259.  
  260.     old_emh = XtAppSetWarningMsgHandler(appcontext,
  261.         (XtErrorMsgHandler)trap_colormaps);
  262.     XtGetApplicationResources(toplevel, (XtPointer)&appres, resources,
  263.         num_resources, 0, 0);
  264.     (void) XtAppSetWarningMsgHandler(appcontext, old_emh);
  265.  
  266. #if defined(USE_APP_DEFAULTS) /*[*/
  267.     /* Check the app-defaults version. */
  268.     if (!appres.ad_version)
  269.         XtError("Outdated app-defaults file");
  270.     else if (!strcmp(appres.ad_version, "fallback"))
  271.         XtError("No app-defaults file");
  272.     else if (strcmp(appres.ad_version, app_defaults_version))
  273.         xs_error("app-defaults version mismatch: want %s, got %s",
  274.             app_defaults_version, appres.ad_version);
  275. #endif /*]*/
  276.  
  277. #if defined(LOCAL_PROCESS) /*[*/
  278.     /* Pick out the -e option. */
  279.     parse_local_process(&argc, argv, &cl_hostname);
  280. #endif /*]*/
  281.  
  282.     /* Pick out -set and -clear toggle options. */
  283.     parse_set_clear(&argc, argv);
  284.  
  285.     /* Verify command-line syntax. */
  286.     switch (argc) {
  287.         case 1:
  288. #if !defined(X3270_MENUS) /*[*/
  289.         if (cl_hostname == CN)
  290.             usage(CN);
  291. #endif /*]*/
  292.         break;
  293.         case 2:
  294.         if (cl_hostname != CN)
  295.             usage(CN);
  296.         no_minus(argv[1]);
  297.         cl_hostname = argv[1];
  298.         break;
  299.         case 3:
  300.         if (cl_hostname != CN)
  301.             usage(CN);
  302.         no_minus(argv[1]);
  303.         no_minus(argv[2]);
  304.         cl_hostname = xs_buffer("%s:%s", argv[1], argv[2]);
  305.         break;
  306.         default:
  307.         usage(CN);
  308.         break;
  309.     }
  310.  
  311.     default_screen = DefaultScreen(display);
  312.     root_window = RootWindow(display, default_screen);
  313.     screen_depth = DefaultDepthOfScreen(XtScreen(toplevel));
  314.  
  315.     /* Sort out model, color and extended data stream modes. */
  316.     appres.model = XtNewString(appres.model);
  317.     if (!strncmp(appres.model, "3278", 4)) {
  318.         appres.m3279 = False;
  319.         appres.model = appres.model + 4;
  320.         if (appres.model[0] == '-')
  321.             ++appres.model;
  322.     } else if (!strncmp(appres.model, "3279", 4)) {
  323.         appres.m3279 = True;
  324.         appres.model = appres.model + 4;
  325.         if (appres.model[0] == '-')
  326.             ++appres.model;
  327.     }
  328.     sl = strlen(appres.model);
  329.     if (sl && (appres.model[sl-1] == 'E' || appres.model[sl-1] == 'e')) {
  330.         appres.extended = True;
  331.         appres.model[sl-1] = '\0';
  332.         sl--;
  333.         if (sl && appres.model[sl-1] == '-')
  334.             appres.model[sl-1] = '\0';
  335.     }
  336.     if (!appres.model[0])
  337. #if defined(RESTRICT_3279) /*[*/
  338.         appres.model = XtNewString("3");
  339. #else /*][*/
  340.         appres.model = XtNewString("4");
  341. #endif /*]*/
  342.     if (appres.m3279)
  343.         appres.extended = True;
  344.     if (screen_depth <= 1 || colormap_failure)
  345.         appres.mono = True;
  346.     if (appres.mono) {
  347.         appres.use_cursor_color = False;
  348.         appres.m3279 = False;
  349.     }
  350.     if (!appres.extended)
  351.         appres.oversize = CN;
  352.     if (appres.secure)
  353.         appres.disconnect_clear = True;
  354.  
  355.     a_delete_me = XInternAtom(display, "WM_DELETE_WINDOW", False);
  356.     a_save_yourself = XInternAtom(display, "WM_SAVE_YOURSELF", False);
  357.     a_3270 = XInternAtom(display, "3270", False);
  358.     a_registry = XInternAtom(display, "CHARSET_REGISTRY", False);
  359.     a_ISO8859 = XInternAtom(display, "ISO8859", False);
  360.     a_iso8859 = XInternAtom(display, "iso8859", False);
  361.     a_encoding = XInternAtom(display, "CHARSET_ENCODING", False);
  362.     a_1 = XInternAtom(display, "1", False);
  363.     a_state = XInternAtom(display, "WM_STATE", False);
  364.  
  365.     XtAppAddActions(appcontext, actions, actioncount);
  366.  
  367.     /* Initialize fonts. */
  368.     font_init();
  369.  
  370. #if defined(RESTRICT_3279) /*[*/
  371.     if (appres.m3279 && !strcmp(appres.model, "4"))
  372.         appres.model = "3";
  373. #endif /*]*/
  374.     if (!appres.extended || appres.oversize == CN ||
  375.         sscanf(appres.oversize, "%dx%d%c", &ovc, &ovr, &junk) != 2) {
  376.         ovc = 0;
  377.         ovr = 0;
  378.     }
  379.     set_rows_cols(atoi(appres.model), ovc, ovr);
  380.     if (appres.termname != CN)
  381.         termtype = appres.termname;
  382.     else
  383.         termtype = full_model_name;
  384.  
  385.     hostfile_init();
  386.  
  387.     keymap_init(appres.key_map);
  388.  
  389.     if (appres.apl_mode) {
  390.         appres.compose_map = XtNewString(Apl);
  391.         appres.charset = XtNewString(Apl);
  392.     }
  393.     if (!charset_init(appres.charset))
  394.         xs_warning("Cannot find charset \"%s\"", appres.charset);
  395.  
  396.     /* Initialize the icon. */
  397.     icon_init();
  398.  
  399.     /*
  400.      * If no hostname is specified on the command line, ignore certain
  401.      * options.
  402.      */
  403.     if (argc <= 1) {
  404. #if defined(LOCAL_PROCESS) /*[*/
  405.         if (cl_hostname == CN)
  406. #endif /*]*/
  407.             appres.once = False;
  408.         appres.reconnect = False;
  409.     }
  410.  
  411. #if !defined(X3270_MENUS) /*[*/
  412.     /*
  413.      * If there are no menus, then -once is the default; let -reconnect
  414.      * override it.
  415.      */
  416.     if (appres.reconnect)
  417.         appres.once = False;
  418. #endif /*]*/
  419.  
  420.     if (appres.char_class != CN)
  421.         reclass(appres.char_class);
  422.  
  423.     screen_init();
  424.     kybd_init();
  425.     ansi_init();
  426.     sms_init();
  427.     error_popup_init();
  428.     info_popup_init();
  429. #if defined(X3270_FT) && !defined(X3270_MENUS) /*[*/
  430.     ft_init();
  431. #endif /*]*/
  432.  
  433.     protocols[0] = a_delete_me;
  434.     protocols[1] = a_save_yourself;
  435.     XSetWMProtocols(display, XtWindow(toplevel), protocols, 2);
  436.  
  437.     /* Save the command line. */
  438.     save_init(argc, argv[1], argv[2]);
  439.  
  440. #ifndef AMIGA
  441.     /* Make sure we don't fall over any SIGPIPEs. */
  442.     (void) signal(SIGPIPE, SIG_IGN);
  443. #endif
  444.  
  445.     /* Set up the window and icon labels. */
  446.     label_init();
  447.  
  448.     /* Handle initial toggle settings. */
  449. #if defined(X3270_TRACE) /*[*/
  450.     if (!appres.debug_tracing) {
  451.         appres.toggle[DS_TRACE].value = False;
  452.         appres.toggle[EVENT_TRACE].value = False;
  453.     }
  454. #endif /*]*/
  455.     initialize_toggles();
  456.  
  457.     /* Connect to the host. */
  458.     if (cl_hostname != CN)
  459.         (void) host_connect(cl_hostname);
  460.  
  461.     /* Prepare to run a peer script. */
  462.     peer_script_init();
  463.  
  464.     /* Process X events forever. */
  465.     while (1) {
  466.         XEvent        event;
  467.  
  468.         while (XtAppPending(appcontext) & (XtIMXEvent | XtIMTimer)) {
  469.             if (XtAppPeekEvent(appcontext, &event))
  470.                 peek_at_xevent(&event);
  471.             XtAppProcessEvent(appcontext,
  472.                 XtIMXEvent | XtIMTimer);
  473.         }
  474.         screen_disp();
  475.         XtAppProcessEvent(appcontext, XtIMAll);
  476.  
  477.         if (children
  478. #ifndef AMIGA
  479.                  && waitpid(0, (int *)0, WNOHANG) > 0
  480. #endif
  481.                    )
  482.             --children;
  483.     }
  484. }
  485.  
  486. /* Change the window and icon labels. */
  487. static void
  488. relabel(Boolean ignored unused)
  489. {
  490.     char *title;
  491.     char icon_label[8];
  492.  
  493.     if (user_title != CN && user_icon_name != CN)
  494.         return;
  495.     title = XtMalloc(10 + ((PCONNECTED || appres.reconnect) ?
  496.                         strlen(reconnect_host) : 0));
  497.     if (PCONNECTED || appres.reconnect) {
  498.         (void) sprintf(title, "x3270-%d%s %s", model_num,
  499.             (IN_ANSI ? "A" : ""), reconnect_host);
  500.         if (user_title == CN)
  501.             XtVaSetValues(toplevel, XtNtitle, title, NULL);
  502.         if (user_icon_name == CN)
  503.             XtVaSetValues(toplevel,
  504.                 XtNiconName, reconnect_host,
  505.                 NULL);
  506.         set_aicon_label(reconnect_host);
  507.     } else {
  508.         (void) sprintf(title, "x3270-%d", model_num);
  509.         (void) sprintf(icon_label, "x3270-%d", model_num);
  510.         if (user_title == CN)
  511.             XtVaSetValues(toplevel, XtNtitle, title, NULL);
  512.         if (user_icon_name == CN)
  513.             XtVaSetValues(toplevel, XtNiconName, icon_label, NULL);
  514.         set_aicon_label(icon_label);
  515.     }
  516.     XtFree(title);
  517. }
  518.  
  519. /* Respect the user's label/icon wishes and set up the label/icon callbacks. */
  520. static void
  521. label_init(void)
  522. {
  523.     user_title = get_resource(XtNtitle);
  524.     user_icon_name = get_resource(XtNiconName);
  525.     if (user_icon_name != CN)
  526.         set_aicon_label(user_icon_name);
  527.  
  528.     register_schange(ST_HALF_CONNECT, relabel);
  529.     register_schange(ST_CONNECT, relabel);
  530.     register_schange(ST_3270_MODE, relabel);
  531.     register_schange(ST_REMODEL, relabel);
  532. }
  533.  
  534. /*
  535.  * Peek at X events before Xt does, calling PA_KeymapNotify_action if we see a
  536.  * KeymapEvent.  This is to get around an (apparent) server bug that causes
  537.  * Keymap events to come in with a window id of 0, so Xt never calls our
  538.  * event handler.
  539.  *
  540.  * If the bug is ever fixed, this code will be redundant but harmless.
  541.  */
  542. static void
  543. peek_at_xevent(XEvent *e)
  544. {
  545.     static Cardinal zero = 0;
  546.  
  547.     if (e->type == KeymapNotify) {
  548.         ia_cause = IA_PEEK;
  549.         PA_KeymapNotify_action((Widget)NULL, e, (String *)NULL, &zero);
  550.     }
  551. }
  552.  
  553.  
  554. /*
  555.  * Warning message trap, for catching colormap failures.
  556.  */
  557. static void
  558. trap_colormaps(String name, String type, String class, String defaultp,
  559.     String *params, Cardinal *num_params)
  560. {
  561.     if (!strcmp(type, "cvtStringToPixel"))
  562.         colormap_failure = True;
  563.     (*old_emh)(name, type, class, defaultp, params, num_params);
  564. }
  565.  
  566. #if defined(LOCAL_PROCESS) /*[*/
  567. /*
  568.  * Pick out the -e option.
  569.  */
  570. static void
  571. parse_local_process(int *argcp, char **argv, char **cmds)
  572. {
  573.     int i, j;
  574.     int e_len = -1;
  575.  
  576.     for (i = 1; i < *argcp; i++) {
  577.         if (strcmp(argv[i], OptLocalProcess))
  578.             continue;
  579.  
  580.         /* Matched.  Copy 'em. */
  581.         e_len = strlen(OptLocalProcess) + 1;
  582.         for (j = i+1; j < *argcp; j++) {
  583.             e_len += 1 + strlen(argv[j]);
  584.         }
  585.         e_len++;
  586.         *cmds = XtMalloc(e_len);
  587.         (void) strcpy(*cmds, OptLocalProcess);
  588.         for (j = i+1; j < *argcp; j++) {
  589.             (void) strcat(strcat(*cmds, " "), argv[j]);
  590.         }
  591.  
  592.         /* Stamp out the remaining args. */
  593.         *argcp = i;
  594.         argv[i] = CN;
  595.         break;
  596.     }
  597. }
  598. #endif /*]*/
  599.  
  600. /*
  601.  * Pick out -set and -clear toggle options.
  602.  */
  603. static void
  604. parse_set_clear(int *argcp, char **argv)
  605. {
  606.     int i, j;
  607.     int argc_out = 0;
  608.     char **argv_out = (char **) XtMalloc((*argcp + 1) * sizeof(char *));
  609.  
  610.     argv_out[argc_out++] = argv[0];
  611.  
  612.     for (i = 1; i < *argcp; i++) {
  613.         Boolean is_set = False;
  614.  
  615.         if (!strcmp(argv[i], OptSet))
  616.             is_set = True;
  617.         else if (strcmp(argv[i], OptClear)) {
  618.             argv_out[argc_out++] = argv[i];
  619.             continue;
  620.         }
  621.  
  622.         if (i == *argcp - 1)    /* missing arg */
  623.             continue;
  624.  
  625.         /* Delete the argument. */
  626.         i++;
  627.  
  628.         for (j = 0; j < N_TOGGLES; j++)
  629.             if (!strcmp(argv[i], toggle_names[j].name)) {
  630.                 appres.toggle[toggle_names[j].index].value =
  631.                     is_set;
  632.                 break;
  633.             }
  634.         if (j >= N_TOGGLES)
  635.             usage("Unknown toggle name");
  636.  
  637.     }
  638.     *argcp = argc_out;
  639.     argv_out[argc_out] = CN;
  640.     (void) memcpy((char *)argv, (char *)argv_out,
  641.         (argc_out + 1) * sizeof(char *));
  642.     XtFree((XtPointer)argv_out);
  643. }
  644.